package com.zebra.remoting.tms;

import cn.hutool.core.util.RandomUtil;
import com.zebra.remoting.config.TmsServerInfo;
import com.zebra.remoting.connection.Connection;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

public class TmsConfigInfoManager {
    private static final InternalLogger logger = InternalLoggerFactory.getInstance(TmsConfigInfoManager.class);

    private static TmsConfigInfoManager configInfoManager = new TmsConfigInfoManager();

    private TmsServerInfo serverInfo;


    /* 多个注册中心 */
    private CopyOnWriteArrayList<Connection> registers = new CopyOnWriteArrayList();
    /* key: serverId,  对应多个connection */
    private ConcurrentHashMap<Integer, CopyOnWriteArrayList<Connection>> gateways = new ConcurrentHashMap(4);


    public static TmsConfigInfoManager getInstance() {
        return configInfoManager;
    }


    //-----------------register-----------------------
    public void registerConnection(Connection connection){
        registers.add(connection);
    }

    public Connection getRAConnection(){
//        return registers.stream().filter(Connection::isFine).sorted(Comparator.comparing(Connection::getServerId)).findFirst().orElse(null);
        List<Connection> registerList = registers.stream().filter(Connection::isFine).collect(Collectors.toList());
        int size = registerList.size();
        return size == 0 ? null : size == 1 ? registerList.get(0) : registerList.get(RandomUtil.randomInt(0, size));
    }

    public List<Connection> findRegisterALL(){
        return registers;
    }

    public void removeRegister(Connection connection){
        registers.remove(connection);
    }
    public void setServerInfo(TmsServerInfo tmsServerInfo){
        this.serverInfo = tmsServerInfo;
    }

    public TmsServerInfo getServerInfo(){
        return this.serverInfo;
    }

    public int getRaSize(){
        return registers.size();
    }


    //-----------------gateway------------------------
    public void registerGateway(Connection connection){
        CopyOnWriteArrayList<Connection> list = gateways.get(connection.getServerId());
        if (null == list){
            list = new CopyOnWriteArrayList<>();
            list.add(connection);
            gateways.put(connection.getServerId(), list);
            return;
        }
        list.add(connection);
    }

    public Connection getGatewayConnection(int serverId, long userId){
        List<Connection> list = findGatewayList(serverId);
        if (null == list){
            return null;
        }
        int index = (int) (userId % list.size());
        return list.get(index);
    }

    private List<Connection> findGatewayList(int serverId){
        List<Connection> list = gateways.get(serverId);
        if (null == list || list.isEmpty()){
            return null;
        }
        List<Connection>  connectionList = list.stream().filter(Connection::isFine).collect(Collectors.toList());
        if (null == connectionList || connectionList.isEmpty()){
            gateways.remove(serverId);
        }
        return connectionList;
    }

    public int getGatewaySize(int serverId){
        List<Connection> list = findGatewayList(serverId);
        return null == list || list.isEmpty() ? 0 : list.size();
    }

    public String buildGatewayLinkTms(){
        removeGateway();
        return buildLinkTms();
    }

    public void removeGwConnection(Connection connection) throws Exception {
        int sid = connection.getServerId();
        if (null == gateways.get(sid) || gateways.get(sid).isEmpty()){
            return;
        }
        gateways.get(sid).remove(connection);
        if (gateways.get(sid).isEmpty()){
            gateways.remove(sid);
        }
        logger.info(" TMS Server Info {} ", buildLinkTms());
    } private void removeGateway(){
        gateways.forEach((k,v) ->{
            for (Connection c : v){
                c.close();
            }
        });
    }


    public String buildLinkTms(){
        if (gateways.isEmpty() && registers.isEmpty()){
            return "AT";
        }

        int size = (gateways.size() * 8) + (registers.size() * 8) + 5;
        StringBuilder stringBuilder = new StringBuilder(size);
        if (!gateways.isEmpty()){
            Map<Integer, Integer> tmsMap = new HashMap<>(gateways.size());
            gateways.forEach((k, v) -> tmsMap.put(k, getGatewaySize(k)));
            tmsMap.forEach((k, v) -> stringBuilder.append(k).append('-').append(v).append(", "));
        }
        stringBuilder.append("AT ");
        if (!registers.isEmpty()){
            registers.forEach(c -> {
                if (c.isFine()){
                    stringBuilder.append(c.getServerId()).append("-1, ");
                }
            });
        }
        return stringBuilder.toString();
    }



}
